﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DBSourceToolsLib;
using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using Aga.Controls;
using Fireball.Windows.Forms;
using Fireball.Syntax;
using Fireball.CodeEditor.SyntaxFiles;
using DBSourceToolsLib.Composite;

namespace DBSourceTools
{

    public partial class CompareResultsForm : MainPanelForm
    {
        public string TargetDatabaseNick;
        private TreeModel oModel;

        SourceDatabase m_SourceDatabase;
        SourceDatabase m_TargetDatabase;
        CodeEditorControl m_CodeEditSource = new CodeEditorControl();
        CodeEditorControl m_CodeEditTarget = new CodeEditorControl();
        CodeEditorControl m_CodeEditDiff = new CodeEditorControl();

        public CompareResultsForm(string strDBName, string strObjType, string strName)
            : base(strDBName, strObjType, strName)
        {
            InitializeComponent();
            oModel = new TreeModel();
            m_treeViewAdv.Model = oModel;
            
        }

        private void CompareResultsForm_Load(object sender, EventArgs e)
        {
            try
            {
                m_SourceDatabase = UserSettings.Instance().getSourceDatabase(m_DatabaseName);
                m_TargetDatabase = UserSettings.Instance().getSourceDatabase(TargetDatabaseNick);

                this.Text = m_SourceDatabase.DatabaseName + " >> " + m_TargetDatabase.DatabaseName;
                this.TabText = m_SourceDatabase.DatabaseName + " >> " + m_TargetDatabase.DatabaseName;

                m_CodeEditSource.Dock = DockStyle.Fill;
                m_CodeEditTarget.Dock = DockStyle.Fill;
                m_CodeEditDiff.Dock = DockStyle.Fill;
                CodeEditorSyntaxLoader.SetSyntax(m_CodeEditSource, "test.sql");
                CodeEditorSyntaxLoader.SetSyntax(m_CodeEditTarget, "test.sql");
                CodeEditorSyntaxLoader.SetSyntax(m_CodeEditDiff, "test.sql");

                tabPageSourceObject.Controls.Add(m_CodeEditSource);
                tabPageTargetCurrent.Controls.Add(m_CodeEditTarget);
                tabPageDiffScript.Controls.Add(m_CodeEditDiff);

                DBSourceToolsLib.SourceDatabaseLoader oComparer = new SourceDatabaseLoader(
                    this, DBSourceToolsLib.Commands.DatabaseCommandTypes.CompareDatabases);

                oComparer.Execute(ref m_SourceDatabase, TargetDatabaseNick);
                if (oComparer.HasErrors())
                    throw new Exception(oComparer.GetErrorMessage());


                UpdateTreeView();
            }
            catch (Exception ex)
            {
                DBSourceToolsLib.SysObjects.UI.Forms.ErrorForm oError =
                    new DBSourceToolsLib.SysObjects.UI.Forms.ErrorForm(ex.ToString());
                                oError.ShowDialog(this);

            }

        }

        private void UpdateTreeView()
        {
            // TODO : sort schema results alphabetically (pegas)

            //m_treeViewAdv.NodeControls.Clear();
            oModel.Nodes.Clear();
            m_treeViewAdv.BeginUpdate();

            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.Table,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.Tables;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Tables";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Tables");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.TableType,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.TablesTypes;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Table Types";

                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "TableType");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.View,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.Views;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Views";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Views");
                }
            }

            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.StoreProcedure,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.Procedures;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Procedures";

                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Procs");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.FileGroup,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.FileGroups;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "File Groups";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Procs");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.UserDataType,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.UserTypes;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Data Types";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "DataTypes");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.Schema,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.Schemas;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Schemas";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Schemas");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.Trigger,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.DDLTriggers;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Triggers";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Schemas");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.XMLSchema,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.XmlSchemas;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "XML Schemas";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "XmlSchemas");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.Assembly,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.Assemblies;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Assemblies";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Assemblies");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.Function,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.Functions;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "Functions";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Functions");
                }
            }
            {
                DBDiff.Schema.Model.SchemaList<DBDiff.Schema.SQLServer.Generates.Model.CLRStoreProcedure,
                    DBDiff.Schema.SQLServer.Generates.Model.Database> oSchemaList = m_SourceDatabase.TargetDatabase.CLRProcedures;
                if (oSchemaList.Count > 0)
                {
                    MyNode oNode = new MyNode();
                    oNode.Text = "CLR Procedures";
                    oModel.Root.Nodes.Add(oNode);

                    foreach (DBDiff.Schema.Model.ISchemaBase oBase in oSchemaList)
                        AddToListView(oBase, 0, oNode, "Procs");
                }
            }

            m_treeViewAdv.EndUpdate();
            m_treeViewAdv.ExpandAll();
            m_treeViewAdv.Refresh();
        }

        void nodeCheckBox1_IsVisibleValueNeeded(object sender, NodeControlValueEventArgs e)
        {
//            if (e.Node.Children != null)
            MyNode oMyNode = (MyNode)e.Node.Tag;
            e.Value = oMyNode.CanSelect;
            
        }

        private void AddToListView(DBDiff.Schema.Model.ISchemaBase oBase, int iImageIndex, Node oNode, string strObjectType)
        {

            MyNode newNode = new MyNode();
            newNode.Text = oBase.Name;
            newNode.Image = imageList1.Images[iImageIndex];
            newNode.ObjectType = strObjectType;
            newNode.ObjectState = oBase.Status;
            //newNode.Tag = oBase.Name;
            newNode.SQLText = oBase.ToSqlAdd();
            newNode.ObjectFullName = oBase.FullName;
            
            switch (oBase.Status)
            {
                case DBDiff.Schema.Enums.ObjectStatusType.AlterStatus:
                case DBDiff.Schema.Enums.ObjectStatusType.AlterBodyStatus | DBDiff.Schema.Enums.ObjectStatusType.AlterStatus:
                    if (toolStripButtonShowUpdate.Checked)
                    {
                        newNode.StateImage = m_imageListState.Images[0];
                        newNode.TargetObject = oBase.Name;
                        newNode.TargetIcon = imageList1.Images[iImageIndex];
                        newNode.CanSelect = true;
                        newNode.IsModify = true;
                        oNode.Nodes.Add(newNode);
                    }
                    break;
                case DBDiff.Schema.Enums.ObjectStatusType.CreateStatus:
                    if (toolStripButtonShowAdd.Checked)
                    {
                        newNode.StateImage = m_imageListState.Images[1];
                        newNode.CanSelect = true;
                        newNode.IsNew = true;
                        oNode.Nodes.Add(newNode);
                    }
                    break;
                case DBDiff.Schema.Enums.ObjectStatusType.OriginalStatus:
                    if (toolStripButtonShowEqual.Checked) {
                        newNode.StateImage = m_imageListState.Images[2];
                        newNode.IsEqual = true;
                        oNode.Nodes.Add(newNode);
                    }
                    break;
                case DBDiff.Schema.Enums.ObjectStatusType.DropStatus:
                    if ( toolStripButtonDrob.Checked)
                    {
                        newNode.StateImage = m_imageListState.Images[3];
                        newNode.IsEqual = true;
                        oNode.Nodes.Add(newNode);
                    }

                    break;
            }

            
                
        }

        private void m_treeViewAdv_SelectionChanged(object sender, EventArgs e)
        {

            Aga.Controls.Tree.TreeViewAdv oSelNode = (Aga.Controls.Tree.TreeViewAdv)sender;
            if (oSelNode != null)
            {
                if (oSelNode.CurrentNode != null)
                {
                    MyNode oMyNode = (MyNode)oSelNode.CurrentNode.Tag;

                    DBDiff.Schema.Model.ISchemaBase iSchemaSourceBase = m_SourceDatabase.OriginalSourceDatabase.Find(oMyNode.ObjectFullName);
                    if (iSchemaSourceBase != null)
                    {
                        m_CodeEditSource.Document.Text = iSchemaSourceBase.ToSql();
                    }
                    else
                        m_CodeEditSource.Document.Text = "";

                    DBDiff.Schema.Model.ISchemaBase iSchemaBase = m_SourceDatabase.TargetDatabase.Find(oMyNode.ObjectFullName);
                    if (iSchemaBase != null)
                    {
                        m_CodeEditDiff.Document.Text = iSchemaBase.ToSqlDiff().ToSQL();
                    }
                    else
                        m_CodeEditDiff.Document.Text = "";
                    

                    DBDiff.Schema.Model.ISchemaBase iSchemaBaseTarget = m_SourceDatabase.OriginalTargetDatabase.Find(oMyNode.ObjectFullName);
                    if (iSchemaBaseTarget != null)
                        m_CodeEditTarget.Document.Text = iSchemaBaseTarget.ToSql();
                    else
                        m_CodeEditTarget.Document.Text = "";
                }
            }
        }

        private void toolStripButton_Script_Click(object sender, EventArgs e)
        {
            try
            {
                string strNewQueryName;// = this.m_TargetDatabase.SysObjects.NewQueryName();

                DBSourceToolsLib.SourceDatabaseLoader oCompareLoader = new SourceDatabaseLoader(
                    this, DBSourceToolsLib.Commands.DatabaseCommandTypes.NewQuery);

                oCompareLoader.Execute(ref m_TargetDatabase, "");
                if (oCompareLoader.HasErrors())
                    throw new Exception(oCompareLoader.GetErrorMessage());

                strNewQueryName = oCompareLoader.NewQueryName;

                DBSourceToolsLib.SysObjects.SysObject oNewQuery =
                    this.m_TargetDatabase.SysObjects.getSysObject("Queries", strNewQueryName);

                oNewQuery.Text = m_SourceDatabase.DiffScript.Replace("\r",
                   "");

                oNewQuery.WriteFile(false, true, null, false);

                WindowList.Instance().ShowWindow(new TreeNodeTag(m_TargetDatabase.NickName, "File", oCompareLoader.NewQueryFileName, null));

            }
            catch (Exception ex)
            {
                DBSourceToolsLib.SysObjects.UI.Forms.ErrorForm oError =
                    new DBSourceToolsLib.SysObjects.UI.Forms.ErrorForm(ex.ToString());
                oError.ShowDialog(this);

            }

        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            UpdateTreeView();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            UpdateTreeView();
        }

        private void toolStripButtonShowUpdate_Click(object sender, EventArgs e)
        {
            UpdateTreeView();
        }

        private void toolStripButtonDrob_Click(object sender, EventArgs e)
        {
            UpdateTreeView();
        }

    }

    public class MyNode : Aga.Controls.Tree.Node
    {
        public string State;
        public Image StateImage;
        public string TargetObject;
        public Image TargetIcon;
        public string ObjectType;
        public DBDiff.Schema.Enums.ObjectStatusType ObjectState;
        public string SQLText;
        public bool CanSelect = false;
        public bool IsEqual = false;
        public bool IsNew = false;
        public bool IsModify = false;
        public string ObjectFullName;
    }

}
